package com.linkoog.devtools.archive.action.zip;

import com.intellij.ide.projectView.ProjectView;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComponentWithBrowseButton;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.TextComponentAccessor;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.ui.ValidationInfo;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.linkoog.devtools.intellij.ui.file_browse.BrowseFolderActionListener;
import com.linkoog.devtools.utils.StringUtils;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.awt.*;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;

public class ZipFileDialog extends DialogWrapper {

    private final Project project;
    private final ArrayList<VirtualFile> files;
    private final VirtualFile fristVirtualFile;

    private JPanel myMainPanel;
    private JTextField fileNameTextField;

    private JPanel outputPanel;
    private TextFieldWithBrowseButton outputPathTextField;
    private JTextField chatsetTextField;
    private JCheckBox rootDirCheckBox;
    private JCheckBox fastModeCheckBox;


    public ZipFileDialog(@NotNull Project project, @NotNull ArrayList<VirtualFile> files) {
        super(project, false);
        if (files.isEmpty()) throw new IllegalArgumentException("files is empty");
        this.fristVirtualFile = files.get(0);

        this.project = project;
        this.files = files;

        initPanel();
        init();
    }

    @Override
    protected void init() {
        super.init();
        getWindow().setMinimumSize(new Dimension(425, 220));
        myMainPanel.setMinimumSize(new Dimension(425, 220));
    }


    private void initPanel() {
        if (files.size() == 1) {
            fileNameTextField.setText(fristVirtualFile.getNameWithoutExtension());
            outputPathTextField.setText(fristVirtualFile.getParent().getCanonicalPath());
        } else {
            fileNameTextField.setText("Archive");
            outputPathTextField.setText(project.getBasePath());
        }

        // 创建一个FileChooserDescriptor，指定我们想要选择文件（true）、选择目录（false）、使用JARS（false）、使用JAR内容（false）、显示隐藏文件（false）以及接受所有文件（true）。
        FileChooserDescriptor fileChooserDescriptor = new FileChooserDescriptor(false, true, false, false, false, false);
        fileChooserDescriptor.setTitle("Select Dir");
        fileChooserDescriptor.setDescription("Please select the dir.");

        outputPathTextField.addActionListener(new BrowseFolderActionListener<>(outputPathTextField, project, fileChooserDescriptor, TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT));

        chatsetTextField.setText("UTF-8");
        chatsetTextField.setEditable(false);

        rootDirCheckBox.setSelected(true);
    }

    @Override
    protected ValidationInfo doValidate() {
        String fileName = this.fileNameTextField.getText();
        if (StringUtils.isBlank(fileName)){
            return new ValidationInfo("文件名不能为空", fileNameTextField);
        }

        if (fileName.endsWith(".zip")){
            return new ValidationInfo("文件名不能带文件类型", fileNameTextField);
        }


        String outputPath = this.outputPathTextField.getText();
        if (StringUtils.isBlank(outputPath)){
            return new ValidationInfo("output不能为空", outputPathTextField);
        }

        File file = new File(outputPath);
        if (!file.exists() || !file.isDirectory()){
            return new ValidationInfo("output路径不是文件夹", outputPathTextField);
        }

        return null;
    }

    @Override
    protected void doOKAction() {
        String fileName = this.fileNameTextField.getText();
        String outputPath = this.outputPathTextField.getText();
        boolean addRootDirFlag = rootDirCheckBox.isSelected();
        boolean fastModeFlag = fastModeCheckBox.isSelected();
        zip(project,files, fileName, outputPath, addRootDirFlag, fastModeFlag);
        super.doOKAction();
    }

    private void zip(Project project, ArrayList<VirtualFile> files, String fileName, String outputPath,  boolean addRootDirFlag, boolean fastModeFlag ) {
        ApplicationManager.getApplication().executeOnPooledThread(() -> {
            ProgressManager.getInstance().run(new Task.Backgroundable(project, "Zipping files", true) {
                @Override
                public void run(@NotNull ProgressIndicator progressIndicator) {
                    progressIndicator.setText("Zipping task start...");
                    long startTime = System.currentTimeMillis();
                    try {
                        progressIndicator.setText("Calculate Zip task");
                        LinkedHashMap<String, Path> archiveFiles = new LinkedHashMap<>();

                        if (files.size() == 1) {
                            for (VirtualFile virtualFile : files) {
                                if (addRootDirFlag){
                                    archiveFiles.putAll(ZipHandler.handler(fileName, virtualFile.toNioPath()));
                                } else {
                                    archiveFiles.putAll(ZipHandler.handler("", virtualFile.toNioPath()));
                                }
                            }
                        } else {
                            for (VirtualFile virtualFile : files) {
                                if (virtualFile.isDirectory()){
                                    if (addRootDirFlag){
                                        archiveFiles.putAll(ZipHandler.handler(fileName + "/" + virtualFile.getName(), virtualFile.toNioPath()));
                                    } else {
                                        archiveFiles.putAll(ZipHandler.handler("/" + virtualFile.getName(), virtualFile.toNioPath()));
                                    }
                                } else {
                                    if (addRootDirFlag){
                                        archiveFiles.putAll(ZipHandler.handler(fileName, virtualFile.toNioPath()));
                                    } else {
                                        archiveFiles.putAll(ZipHandler.handler("", virtualFile.toNioPath()));
                                    }
                                }
                            }
                        }


                        ZipHandler.zip(archiveFiles, outputPath, fileName + ".zip");
                    }catch (Throwable throwable){
                        progressIndicator.setText("Fail to execute the Zip task: " + throwable.getMessage());
                    }
                    // 刷新文件树
                    ProjectView.getInstance(project).refresh();
                    // 刷新虚拟文件系统的缓存
                    VirtualFileManager.getInstance().asyncRefresh(null);
                    progressIndicator.setText("Zipping task complete, cost time: " + (System.currentTimeMillis() - startTime) + "ms");
                }
            });
        });
    }

    @Override
    protected JComponent createCenterPanel() {
        return myMainPanel;
    }

    private void createUIComponents() {
        // 创建TextFieldWithBrowseButton组件
        outputPathTextField = new TextFieldWithBrowseButton();
        outputPanel = outputPathTextField;

    }
}
